package com.dd.cloud.user.mq;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

/**
 * 队列
 *
 * @author zk
 */
@Configuration
@Slf4j
public class MQConfig {
    /**
     * 操作日志队列
     */
    public static final String LOG_OPER_QUERE = "dd.oper.log.queue";
    /**
     * 操作日志交换机
     */
    public static final String LOG_OPER_EXCHANGE = "dd.oper.log.exchange";
    /**
     * 异常日志队列
     */
    public static final String LOG_EXC_QUERE = "dd.exc.log.queue";
    /**
     * 异常日志交换机
     */
    public static final String LOG_EXC_EXCHANGE = "dd.exc.log.exchange";
    /**
     * 短信队列
     */
    public static final String SMS_QUERE = "dd.sms.msg.queue";
    /**
     * 短信交互机
     */
    public static final String SMS_EXCHANGE = "dd.sms.exchange";
    /**
     * 短信路由
     */
    public static final String SMS_KEY = "dd.sms.msg";
    /**
     * 延迟队列交换机
     */
    public static final String DELAY_EXCHANGE = "dd.delay.exchange";
    /**
     * 路由key
     */
    public static final String DELAY_KEY = "dd.delay.key";
    /**
     * 队列名称
     */
    public static final String DELAY_QUEUE = "dd.delay.queue";
    /**
     * 生成处方pdf队列
     */
    public static final String PRES_PDF_QUERE = "dd.pres.pdf.queue";
    /**
     * 生成处方pdf交换机
     */
    public static final String PRES_PDF_EXCHANGE = "dd.pres.log.exchange";
    /**
     * 生成模板队列
     */
    public static final String TEMPLATE_QUEUE = "dd.template.queue";
    /**
     * 生成模板交换机
     */
    public static final String TEMPLATE_EXCHANGE = "dd.template.exchange";

    /**
     * app消息队列
     */
    public static final String APP_NEWS_QUEUE = "dd.app.news.queue";
    /**
     * app消息交换机
     */
    public static final String APP_NEWS_EXCHANGE = "dd.app.news.exchange";

    /**
     * 生成积分队列
     */
    public static final String INTEGRAL_QUEUE = "dd.integral.queue";
    /**
     * 生成积分交换机
     */
    public static final String INTEGRAL_EXCHANGE = "dd.integral.exchange";




    @Bean
    public RabbitListenerContainerFactory<?> rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        //开启手动 ack
        factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
        return factory;
    }


    /**
     * 定义一个队列 消息队列
     * Queue 可以有4个参数
     * 1.队列名
     * 2.durable       持久化消息队列 ,rabbitmq重启的时候不需要创建新的队列 默认true
     * 3.auto-delete   表示消息队列没有在使用时将被自动删除 默认是false
     * 4.exclusive     表示该消息队列是否只在当前connection生效,默认是false
     */
    @Bean(name = "logOperQueue")
    public Queue logOperQueue() {
        return new Queue(LOG_OPER_QUERE, true, false, false);
    }

    /**
     * 定义交换机 消息队列交换机
     *
     * @return
     */
    @Bean(name = "logOperExchange")
    public FanoutExchange logOperExchange() {
        return new FanoutExchange(LOG_OPER_EXCHANGE);
    }

    /**
     * 将队列绑定到交换机上
     *
     * @param confirmTestExchange
     * @param confirmTestQueue
     * @return
     */
    @Bean
    public Binding confirmLogOperExchangeAndQueue(
            @Qualifier("logOperExchange") FanoutExchange confirmTestExchange,
            @Qualifier("logOperQueue") Queue confirmTestQueue) {
        return BindingBuilder.bind(confirmTestQueue).to(confirmTestExchange);
    }

    /**
     * 定义一个队列 消息队列
     * Queue 可以有4个参数
     * 1.队列名
     * 2.durable       持久化消息队列 ,rabbitmq重启的时候不需要创建新的队列 默认true
     * 3.auto-delete   表示消息队列没有在使用时将被自动删除 默认是false
     * 4.exclusive     表示该消息队列是否只在当前connection生效,默认是false
     */
    @Bean(name = "logExcQueue")
    public Queue logExcQueue() {
        return new Queue(LOG_EXC_QUERE, true, false, false);
    }

    /**
     * 定义交换机 消息队列交换机
     *
     * @return
     */
    @Bean(name = "logExcExchange")
    public FanoutExchange logExcExchange() {
        return new FanoutExchange(LOG_EXC_EXCHANGE);
    }

    /**
     * 将队列绑定到交换机上
     *
     * @param confirmTestExchange
     * @param confirmTestQueue
     * @return
     */
    @Bean
    public Binding confirmTestFanoutExchangeAndQueue(
            @Qualifier("logExcExchange") FanoutExchange confirmTestExchange,
            @Qualifier("logExcQueue") Queue confirmTestQueue) {
        return BindingBuilder.bind(confirmTestQueue).to(confirmTestExchange);
    }

    /**
     * 定义一个队列 消息队列
     * Queue 可以有4个参数
     * 1.队列名
     * 2.durable       持久化消息队列 ,rabbitmq重启的时候不需要创建新的队列 默认true
     * 3.auto-delete   表示消息队列没有在使用时将被自动删除 默认是false
     * 4.exclusive     表示该消息队列是否只在当前connection生效,默认是false
     */
    @Bean(name = "presPdfQueue")
    public Queue presPdfQueue() {
        return new Queue(PRES_PDF_QUERE, true, false, false);
    }

    /**
     * 定义交换机 消息队列交换机
     *
     * @return
     */
    @Bean(name = "presPdfExchange")
    public FanoutExchange presPdfExchange() {
        return new FanoutExchange(PRES_PDF_EXCHANGE);
    }

    /**
     * 将队列绑定到交换机上
     *
     * @param confirmTestExchange
     * @param confirmTestQueue
     * @return
     */
    @Bean
    public Binding presPdfExchangeAndQueue(
            @Qualifier("presPdfExchange") FanoutExchange confirmTestExchange,
            @Qualifier("presPdfQueue") Queue confirmTestQueue) {
        return BindingBuilder.bind(confirmTestQueue).to(confirmTestExchange);
    }

    /**
     * 通知延时队列
     *
     * @return
     */
    @Bean(name = "smsQueue")
    public Queue smsQueue() {
        return new Queue(SMS_QUERE, true, false, false);
    }

    /**
     * 通知延时队列交换机
     *
     * @return
     */
    @Bean(name = "smsExchange")
    public DirectExchange smsExchange() {
        return new DirectExchange(SMS_EXCHANGE);
    }

    /**
     * 将队列绑定到交换机上
     *
     * @param smsExchange
     * @param smsQueue
     * @return
     */
    @Bean
    public Binding smsExchangeAndQueue(
            @Qualifier("smsExchange") DirectExchange smsExchange,
            @Qualifier("smsQueue") Queue smsQueue) {
        return BindingBuilder.bind(smsQueue).to(smsExchange).with(SMS_KEY);
    }

    /**
     * 延时队列交换机
     * 注意这里的交换机类型：CustomExchange
     *
     * @return
     */
    @Bean(name = "delayExchange")
    public CustomExchange delayExchange() {
        Map<String, Object> args = new HashMap<>();
        args.put("x-delayed-type", "direct");
        return new CustomExchange(DELAY_EXCHANGE, "x-delayed-message", true, false, args);
    }

    /**
     * 延时队列
     *
     * @return
     */
    @Bean(name = "delayQueue")
    public Queue delayQueue() {
        return new Queue(DELAY_QUEUE, true);
    }

    /**
     * 给延时队列绑定交换机
     *
     * @return
     */
    @Bean
    public Binding cfgDelayBinding(@Qualifier("delayExchange") CustomExchange delayExchange,
                                   @Qualifier("delayQueue") Queue delayQueue) {
        return BindingBuilder.bind(delayQueue).to(delayExchange).with(DELAY_KEY).noargs();
    }


    /**
     * 定义一个队列 消息队列
     * Queue 可以有4个参数
     * 1.队列名
     * 2.durable       持久化消息队列 ,rabbitmq重启的时候不需要创建新的队列 默认true
     * 3.auto-delete   表示消息队列没有在使用时将被自动删除 默认是false
     * 4.exclusive     表示该消息队列是否只在当前connection生效,默认是false
     */
    @Bean(name = "templateQueue")
    public Queue templateQueue() {
        return new Queue(TEMPLATE_QUEUE, true, false, false);
    }

    /**
     * 定义交换机 消息队列交换机
     *
     * @return
     */
    @Bean(name = "templateExchange")
    public FanoutExchange templateExchange() {
        return new FanoutExchange(TEMPLATE_EXCHANGE);
    }

    /**
     * 将队列绑定到交换机上
     *
     * @param confirmTestExchange
     * @param confirmTestQueue
     * @return
     */
    @Bean
    public Binding templateExchangeAndQueue(
            @Qualifier("templateExchange") FanoutExchange confirmTestExchange,
            @Qualifier("templateQueue") Queue confirmTestQueue) {
        return BindingBuilder.bind(confirmTestQueue).to(confirmTestExchange);
    }

    /**
     * 定义一个队列 消息队列 app消息
     * Queue 可以有4个参数
     * 1.队列名
     * 2.durable       持久化消息队列 ,rabbitmq重启的时候不需要创建新的队列 默认true
     * 3.auto-delete   表示消息队列没有在使用时将被自动删除 默认是false
     * 4.exclusive     表示该消息队列是否只在当前connection生效,默认是false
     */
    @Bean(name = "appNewsQueue")
    public Queue appNewsQueue() {
        return new Queue(APP_NEWS_QUEUE, true, false, false);
    }

    /**
     * 定义交换机 消息队列交换机
     *
     * @return
     */
    @Bean(name = "appNewsExchange")
    public FanoutExchange appNewsExchange() {
        return new FanoutExchange(APP_NEWS_EXCHANGE);
    }

    /**
     * 将队列绑定到交换机上
     *
     * @param confirmTestExchange
     * @param confirmTestQueue
     * @return
     */
    @Bean
    public Binding appNewsExchangeAndQueue(
            @Qualifier("appNewsExchange") FanoutExchange confirmTestExchange,
            @Qualifier("appNewsQueue") Queue confirmTestQueue) {
        return BindingBuilder.bind(confirmTestQueue).to(confirmTestExchange);
    }


    /**
     * 定义一个队列 消息队列
     * Queue 可以有4个参数
     * 1.队列名
     * 2.durable       持久化消息队列 ,rabbitmq重启的时候不需要创建新的队列 默认true
     * 3.auto-delete   表示消息队列没有在使用时将被自动删除 默认是false
     * 4.exclusive     表示该消息队列是否只在当前connection生效,默认是false
     */
    @Bean(name = "integralQueue")
    public Queue integralQueue() {
        return new Queue(INTEGRAL_QUEUE, true, false, false);
    }

    /**
     * 定义交换机 消息队列交换机
     *
     * @return
     */
    @Bean(name = "integralExchange")
    public FanoutExchange integralExchange() {
        return new FanoutExchange(INTEGRAL_EXCHANGE);
    }

    /**
     * 将队列绑定到交换机上
     *
     * @param confirmTestExchange
     * @param confirmTestQueue
     * @return
     */
    @Bean
    public Binding integralExchangeAndQueue(
            @Qualifier("integralExchange") FanoutExchange confirmTestExchange,
            @Qualifier("integralQueue") Queue confirmTestQueue) {
        return BindingBuilder.bind(confirmTestQueue).to(confirmTestExchange);
    }
}
